<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>d3 bar race</title>
  <script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script>
  <script src="https://d3js.org/d3.v5.min.js"></script>
  <style>
    body {
      background-color: brown;
    }

    .axis {
      font: 10px sans-serif;
    }

    .axis path,
    .axis line {
      fill: none;
      stroke: #000;
      shape-rendering: crispEdges;
    }

    .tick {
      color: #fff;
    }

    .axis--y path {
      display: none;
    }

    .bar {
      fill: #fa963e;
      fill-opacity: .9;
    }

    .wld {
      fill: #9ecae1;
    }

    .chart-title {
      margin-bottom: 0;

    }

    .source {
      margin-top: 0;
      font-size: 11px;
    }
  </style>
</head>

<body>
  <div class="chart"></div>
  <div id="app">
  </div>
</body>
<script>
  let menuRaceList = [
    [{
        name: '麻婆豆腐',
        count: 1
      },
      {
        name: '酸菜鱼',
        count: 0.76
      },
      {
        name: '甜酸排骨',
        count: 0.54
      },
      {
        name: '苦瓜五花肉',
        count: 0.42
      },
      {
        name: '抹茶奶盖',
        count: 0.13
      }
    ],
    [{
        name: '麻婆豆腐',
        count: 0.90
      },
      {
        name: '酸菜鱼',
        count: 0.82
      },
      {
        name: '抹茶奶盖',
        count: 0.53
      },
      {
        name: '苦瓜五花肉',
        count: 0.38
      },
      {
        name: '甜酸排骨',
        count: 0.18
      }
    ]
  ]

  const margin = {
    top: 20,
    right: 30,
    bottom: 40,
    left: 260
  };
  const width = 960 - margin.left - margin.right;
  const height = 400 - margin.top - margin.bottom;
  const percentFormat = d3.format('.0%');
  const leftPadding = 5;

  const delay = function (d, i) {
    return i * 40;
  };

  function sortData(data) {
    return data.sort((a, b) => b.count - a.count);
  }

  function removeGeoAreasWithNoData(data) {
    return data.filter(d => d.count);
  }

  function prepareData(data) {
    return data.reduce((accumulator, d) => {
      Object.keys(d).forEach((k) => {
        if (!Number.isInteger(+k)) {
          return;
        }
        let value;
        if (d[+k] === '..') {
          value = 0;
        } else {
          value = +d[+k] / 100;
        }
        const newEntry = {
          count: value,
          name,
        };
        if (accumulator[+k]) {
          accumulator[+k].push(newEntry);
        } else {
          accumulator[+k] = [newEntry];
        }
      });
      return accumulator;
    }, {});
  }

  function xAccessor(d) {
    return d.count;
  }

  function yAccessor(d) {
    return d.name;
  }

  const xScale = d3.scaleLinear()
    .range([0, width])
    .domain([0, 1]);

  const yScale = d3.scaleBand()
    .rangeRound([0, height], 0.1)
    .padding(0.1);

  function drawXAxis(el) {
    el.append('g')
      .attr('class', 'axis axis--x')
      .attr('transform', `translate(${leftPadding},${height})`)
      .call(d3.axisBottom(xScale).tickFormat(percentFormat));
  }

  function drawYAxis(el, data, t) {
    let axis = el.select('.axis--y');
    if (axis.empty()) {
      axis = el.append('g')
        .attr('class', 'axis axis--y');
    }

    axis.transition(t)
      .call(d3.axisLeft(yScale))
      .selectAll('g')
      .delay(delay);
  }

  function drawBars(el, data, t) {
    let barsG = el.select('.bars-g');
    if (barsG.empty()) {
      barsG = el.append('g')
        .attr('class', 'bars-g');
    }

    const bars = barsG
      .selectAll('.bar')
      .data(data, yAccessor);
    bars.exit()
      .remove();
    bars.enter()
      .append('rect')
      .attr('class', d => d.name === '甜酸排骨' ? 'bar wld' : 'bar')
      .attr('x', leftPadding)
      .merge(bars).transition(t)
      .attr('y', d => yScale(yAccessor(d)))
      .attr('width', d => xScale(xAccessor(d)))
      .attr('height', yScale.bandwidth())
      .delay(delay);
  }

  const svg = d3.select('.chart').append('svg')
    .attr('width', width + margin.left + margin.right)
    .attr('height', height + margin.top + margin.bottom)
    .append('g')
    .attr('transform', `translate(${margin.left},${margin.top})`);

  // const raceList = [0, 1];
  // const lastRace = 1;
  const data = prepareData(menuRaceList);
  const startRace = sortData(menuRaceList[0]);
  let geoAreas = startRace.map(yAccessor);

  // console.log(startRace);
  yScale.domain(geoAreas);
  // drawXAxis(svg, startRace);
  drawYAxis(svg, startRace);
  drawBars(svg, startRace);


  setTimeout(function () {
    const startRace = sortData(menuRaceList[1]);
    let geoAreas = startRace.map(yAccessor);

    // console.log(startRace);
    yScale.domain(geoAreas);
    // drawXAxis(svg, startRace);
    drawYAxis(svg, startRace);
    drawBars(svg, startRace);
  }, 2000);

  var vm = new Vue({
    el: '#app',
    data() {
      return {
        menuRaceList: [
          [{
              name: '麻婆豆腐',
              count: 94
            },
            {
              name: '酸菜鱼',
              count: 76
            },
            {
              name: '甜酸排骨',
              count: 54
            },
            {
              name: '苦瓜五花肉',
              count: 42
            },
            {
              name: '抹茶奶盖',
              count: 13
            }
          ],
          [{
              name: '麻婆豆腐',
              count: 304
            },
            {
              name: '酸菜鱼',
              count: 196
            },
            {
              name: '甜酸排骨',
              count: 154
            },
            {
              name: '抹茶奶盖',
              count: 113
            },
            {
              name: '苦瓜五花肉',
              count: 92
            }
          ]
        ]
      }
    },
    methods: {

    },
    mounted() {

    }
  })
</script>

</html>